package main;

import java.awt.HeadlessException;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;

public class Server {


	public Server()
	{

	}
	public static void main(String args[]) {

		/***
		 * Initialize with the default arguments 
		 */
		String directory = System.getProperty("user.home")+File.separator+"serverdata";
		int j = 1 ; 
		ServerSocket serverSocket ; 
		FileHandler fileHandler = null ; 
		int proc_count_number = 2 ; 
		int serverportnumber =3000; 
		ThreadGroup tgroup = new ThreadGroup("Parent");
		try
		{
			System.setProperty("java.awt.headless", "true");
		}
		catch(HeadlessException he)
		{
			System.out.println("Headless mode not supported ");
			System.exit(0);
		}
		/***
		 * The 1st argument is the serverport
		 */

		if(args.length==1)
		{
			String argument = args[0];

			try{

				serverportnumber = Integer.parseInt(argument);

				if(serverportnumber<1 || serverportnumber>65535)
				{
					System.out.println("Invalid port number");
					System.exit(-1);
				}

				if(serverportnumber > 65535)
				{
					proc_count_number = serverportnumber ; 
					serverportnumber =3000 ; 
				}

			}
			catch(NumberFormatException e)
			{
				directory = argument;
			}
		}

		else if(args.length==2)
		{
			String arg0 = args[0];
			String arg1 = args[1];
			boolean flag = true ; 
			try
			{
				serverportnumber = Integer.parseInt(arg0);
				if(serverportnumber<1 || serverportnumber>65535)
				{
					System.out.println("Invalid port number");
					System.exit(-1);
				}
			}

			catch(NumberFormatException n)
			{
				directory =arg0;
				flag = false ; 
				try
				{
					proc_count_number = Integer.parseInt(arg1);
				}
				catch(NumberFormatException e)
				{
					System.out.println("Invalid proc_count");
					System.exit(-1);
				}
			}
			if(flag)
			{
				try
				{
					proc_count_number = Integer.parseInt(arg1);
				}
				catch(NumberFormatException n)
				{
					directory = arg1 ; 
				}
			}
		}

		if(args.length ==3)
		{
		
			String arg0 = args[0];
			String arg1 =args[1];
			String arg2 = args[2];
			
			try
			{
				 serverportnumber = Integer.parseInt(arg0);

				if(serverportnumber<1 || serverportnumber>65535)
				{
					System.out.println("Invalid port number");
					System.exit(-1);
				}
			}
			catch(NumberFormatException e)
			{

				//System.out.println("Invalid Number");
				//System.exit(-1);
				System.out.println("Invalid argument");
				System.exit(-1);
			}
			
			directory = arg1 ; 
			
			try
			{
				 proc_count_number = Integer.parseInt(arg2);

				if(proc_count_number<2)
				{
					System.out.println("Invalid port number");
					System.exit(-1);
				}
			}
			catch(NumberFormatException e)
			{

				//System.out.println("Invalid Number");
				//System.exit(-1);
				System.out.println("Invalid argument");
				System.exit(-1);
			}

			
		}


		/***
		 * Initializing the variables 
		 */
		serverSocket = null;
		boolean listening = true;
		try {

			/***
			 * A single fileHandler object exists between all the threads 
			 */
			fileHandler = new FileHandler(directory);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}


		/**
		 * The threadGroup will keep a tab of all the thread in the server
		 */
		ArrayList<ServerThread> threadGroup = new ArrayList<ServerThread>();
		while (listening)
		{

			try {
				if(serverSocket == null || serverSocket.isClosed())
					serverSocket = new ServerSocket(serverportnumber);
			} catch (IOException e) {
				System.err.println("Could not listen on port: " + serverportnumber);
				System.exit(-1);
			}


			try {

				/***
				 * If count of requests < no of alloted threads , create a new thread
				 */
				if(j<proc_count_number)
				{

					ServerThread t = new ServerThread(serverSocket.accept(),fileHandler,tgroup,j);
					threadGroup.add(t);

					t.start() ; 

					j++;
				}

				/***
				 * Else use a free thread to comply the incoming request
				 */
				else
				{
					for(int i = 0 ; i < threadGroup.size();i++)
					{
						if(threadGroup.get(i).getWaiting()==true)
						{
							ServerThread thread = threadGroup.get(i);
							thread.setSocket(serverSocket.accept());
							thread.setWaiting(false);

							break ; 
						}
					}
				}

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		try {
			serverSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


}



